home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / lfs / lfsBlockIO.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  7.7 KB  |  245 lines

  1. /* 
  2.  * lfsBlockIO.c --
  3.  *
  4.  *    Routines for handling block allocate and access of files in a 
  5.  *    LFS file system. This routines are used by the cache code or
  6.  *    read and allocate files.
  7.  *
  8.  * Copyright 1989 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/lfs/lfsBlockIO.c,v 1.11 92/03/19 17:31:53 jhh Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include <sprite.h>
  23. #include <lfs.h>
  24. #include <lfsInt.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsio.h>
  28. #include <fsioFile.h>
  29. #include <fslcl.h>
  30. #include <fscache.h>
  31. #include <fsdm.h>
  32. #include <fsStat.h>
  33.  
  34.  
  35.  
  36. /*
  37.  *----------------------------------------------------------------------
  38.  *
  39.  * Lfs_FileBlockRead --
  40.  *
  41.  *    Read in a cache block.  This routine uses the files'
  42.  *    indexing structure to locate the file block on disk.
  43.  *    This always attempts to read in a full block, but will read
  44.  *    less if at the last block and it isn't full.  In this case,
  45.  *    the remainder of the cache block is zero-filled.
  46.  *
  47.  * Results:
  48.  *    The results of the disk read.
  49.  *
  50.  * Side effects:
  51.  *    The blockPtr->blockSize is modified to
  52.  *    reflect how much data was actually read in.  The unused part
  53.  *    of the block is filled with zeroes so that higher levels can
  54.  *    always assume the block has good stuff in all parts of it.
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58. ReturnStatus
  59. Lfs_FileBlockRead(domainPtr, handlePtr, blockPtr)
  60.     Fsdm_Domain        *domainPtr;    /* Domain of file. */
  61.     register Fsio_FileIOHandle *handlePtr;    /* Handle on a local file. */
  62.     Fscache_Block       *blockPtr;      /* Cache block to read in.  This assumes
  63.                                          * the blockNum, blockAddr (buffer area)
  64.                                          * and blockSize are set.  This modifies
  65.                                          * blockSize if less bytes were read
  66.                                          * because of EOF. */
  67. {
  68.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  69.     register    Fsdm_FileDescriptor *descPtr;
  70.     register             offset;
  71.     register int         numBytes;
  72.     LfsDiskAddr            diskAddress;
  73.     ReturnStatus         status;
  74.  
  75.     LFS_STATS_INC(lfsPtr->stats.blockio.reads);
  76.     status = SUCCESS;
  77.     blockPtr->blockSize = 0;
  78.     numBytes = FS_BLOCK_SIZE;
  79.     offset = blockPtr->blockNum * FS_BLOCK_SIZE;
  80.  
  81.     /*
  82.      * Is a logical file read. Round the size down to the actual
  83.      * last byte in the file.
  84.      */
  85.     descPtr = handlePtr->descPtr;
  86.     if (offset > descPtr->lastByte) {
  87.     numBytes = 0;
  88.     goto exit;
  89.     } else if (offset + numBytes - 1 > descPtr->lastByte) {
  90.     numBytes = descPtr->lastByte - offset + 1;
  91.     }
  92.  
  93.     status = LfsFile_GetIndex(handlePtr, offset / FS_BLOCK_SIZE, 0,
  94.                  &diskAddress);
  95.     if (status != SUCCESS) {
  96.     printf("Lfs_FileBlockRead: Could not setup indexing\n");
  97.     goto exit;
  98.     }
  99.  
  100.     if (!LfsIsNilDiskAddr(diskAddress)) {
  101.     /*
  102.      * Read in the block.  Specify the device, the fragment index,
  103.      * the number of fragments, and the memory buffer.
  104.      */
  105.     int    ioSize = 
  106.         LfsBlocksToBytes(lfsPtr, LfsBytesToBlocks(lfsPtr, numBytes));
  107.     LfsCheckRead(lfsPtr, diskAddress, numBytes);
  108.  
  109.     status = LfsReadBytes(lfsPtr, diskAddress, ioSize, blockPtr->blockAddr);
  110.     if (status != SUCCESS) {
  111.         LfsError(lfsPtr, FAILURE, "Lfs_FileBlockRead: LfsReadBytes failed");
  112.         return status;
  113.     }
  114.     LFS_STATS_ADD(lfsPtr->stats.blockio.bytesReads, ioSize);
  115.     } else {
  116.     /*
  117.      * Zero fill the block.  We're in a 'hole' in the file.
  118.      */
  119.     fs_Stats.blockCache.readZeroFills++;
  120.     bzero(blockPtr->blockAddr, numBytes);
  121.     }
  122.     Fs_StatAdd(numBytes, fs_Stats.gen.fileBytesRead, 
  123.         fs_Stats.gen.fileReadOverflow);
  124. exit:
  125.     /*
  126.      * Define the block size and error fill leftover space.
  127.      */
  128.     if (status == SUCCESS) {
  129.     blockPtr->blockSize = numBytes;
  130.     }
  131.     if (blockPtr->blockSize < FS_BLOCK_SIZE) {
  132.     fs_Stats.blockCache.readZeroFills++;
  133.     bzero(blockPtr->blockAddr + blockPtr->blockSize,
  134.         FS_BLOCK_SIZE - blockPtr->blockSize);
  135.     }
  136.     return(status);
  137. }
  138.  
  139. /*
  140.  *----------------------------------------------------------------------
  141.  *
  142.  * Lfs_FileBlockWrite --
  143.  *
  144.  *      Write out a cache block.  Since lfs maintains its own cache
  145.  *    write back mechanism, this routines should never be called.
  146.  *
  147.  * Results:
  148.  *      FAILURE
  149.  *
  150.  * Side effects:
  151.  *      It panic's.
  152.  *
  153.  *----------------------------------------------------------------------
  154.  */
  155. /*ARGSUSED*/
  156. ReturnStatus
  157. Lfs_FileBlockWrite(domainPtr, handlePtr, blockPtr)
  158.     Fsdm_Domain     *domainPtr;
  159.     Fsio_FileIOHandle *handlePtr;    /* I/O handle for the file. */
  160.     Fscache_Block *blockPtr;    /* Cache block to write out. */
  161. {
  162.     panic("Lfs_FileBlockWrite called\n");
  163.     return FAILURE;
  164. }
  165.  
  166.  
  167. /*
  168.  *----------------------------------------------------------------------
  169.  *
  170.  * Lfs_BlockAllocate --
  171.  *
  172.  *      Allocate disk space for the given file.  This routine only allocates
  173.  *      one block beginning at offset and going for numBytes. 
  174.  *
  175.  * Results:
  176.  *    SUCCESS or FS_NO_DISK_SPACE
  177.  *      
  178.  *
  179.  * Side effects:
  180.  *      The file descriptor is modified to contain pointers to the allocated
  181.  *      blocks.  Also *blockAddrPtr is set to the block that was allocated.
  182.  *
  183.  *----------------------------------------------------------------------
  184.  */
  185. ReturnStatus
  186. Lfs_BlockAllocate(domainPtr, handlePtr, offset, numBytes, flags, blockAddrPtr,
  187.         newBlockPtr)
  188.     Fsdm_Domain        *domainPtr;    /* Domain of file. */
  189.     register Fsio_FileIOHandle *handlePtr;    /* Local file handle. */
  190.     int         offset;        /* Offset to allocate at. */
  191.     int         numBytes;    /* Number of bytes to allocate. */
  192.     int            flags;        /* FSCACHE_DONT_BLOCK */
  193.     int            *blockAddrPtr;     /* Disk address of block allocated. */
  194.     Boolean        *newBlockPtr;    /* TRUE if there was no block allocated
  195.                      * before. */
  196. {
  197.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  198.     int    newLastByte;
  199.     ReturnStatus status;
  200.     Boolean    dirty = FALSE;
  201.     register    Fsdm_FileDescriptor *descPtr;
  202.  
  203.     LFS_STATS_INC(lfsPtr->stats.blockio.allocs);
  204.     /*
  205.      * Block allocates while checkpoints are active. This ensure that
  206.      * the LFS cache backend will be able to clean all LFS files from the
  207.      * cache. We only need worry about files, directory updates get stopped by
  208.      * the dirlog mechanism. In fact, waiting for a checkpoint for a 
  209.      * directory block allocate causes a possible deadlock because the
  210.      * checkpoint waits for directory operations to finish. We also
  211.      * use this mechanism to keep from filling up the cache with blocks
  212.      * that we can't write out.
  213.      */
  214.     descPtr = handlePtr->descPtr;
  215.     if (descPtr->fileType != FS_DIRECTORY) {
  216.     LfsWaitForCleanSegments(lfsPtr);
  217.     } 
  218.     /*
  219.      * First check to see if we can just allocate the bytes.
  220.      */
  221.     newLastByte = offset + numBytes - 1; 
  222.     *blockAddrPtr = FSDM_NIL_INDEX;
  223.     status = LfsFile_GrowBlock(lfsPtr, handlePtr, offset, numBytes);
  224.     if (status == SUCCESS) {
  225.     *newBlockPtr = FALSE;
  226.     *blockAddrPtr = offset / FS_BLOCK_SIZE;
  227.      if (newLastByte > descPtr->lastByte) {
  228.         descPtr->lastByte = newLastByte;
  229.         dirty = TRUE;
  230.      }
  231.     } 
  232.     if ((status == SUCCESS) && descPtr->firstByte == -1 && 
  233.     ((descPtr->fileType == FS_NAMED_PIPE) ||
  234.      (descPtr->fileType == FS_PSEUDO_DEV) ||
  235.      (descPtr->fileType == FS_XTRA_FILE))) {
  236.     descPtr->firstByte = 0;
  237.     dirty = TRUE;
  238.     }
  239.     if (dirty) { 
  240.     descPtr->descModifyTime = Fsutil_TimeInSeconds();
  241.     descPtr->flags |= FSDM_FD_SIZE_DIRTY;
  242.     } 
  243.     return(status);
  244. }
  245.